/* components */
import FormCascader from '@src/component/form/components/FormCascader/FormCascader.vue'
/* hooks */
import { useDialog } from '@hooks/useDialog'
/* hooks */
import {
  useConnectorCardSettingFetchModuleList,
} from '@src/modules/connector/hooks'
/* model */
import { ConnectorFetchAppModulesStorageKey, ConnectorModuleComponentNameEnum, CreateConnectorDialogFieldNameEnum } from '@src/modules/connector/model'
import Field from '@model/entity/Field'
import StorageModuleEnum from '@model/enum/StorageModuleEnum';
/* scss */
import '@src/modules/connector/components/card-item/index.scss'
import '@src/modules/connector/components/create-connector-dialog/name-dialog.scss'
/* vue */
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { CreateElement, ComponentInstance, ComponentRenderProxy, defineComponent, PropType, watch, ref, computed } from 'vue'
import { CommonComponentInstance } from '@model/VC'
/* util */
import { isFalsy } from '@src/util/type'
import { addComponentNamePrefix } from '@src/util/component'
import Log from '@src/util/log'
import locales, { t } from '@src/locales'
import { addConnectorModuleUniqueIdEveryLevel, connectorAppModuleToFormCascaderDataSource } from '@src/modules/connector/util';
import { storageRm } from '@src/util/storage.ts';
import { getRootWindow } from '@src/util/dom';
import { cloneDeep } from 'lodash'



type CreateConnectorDialogFormBuilderScopedSlotDataType = {
  field: Field;
  value: string[]
}

type FieldUpdateResult = {
  field: Field;
  newValue: any;
  oldValue: any;
}

export type ConnectorModuleCreateConnectorNameDialogProps = {
  disabled: boolean;
  nextDisabled: boolean;
  fields: Field[];
  title: string;
  visible: boolean;
  value: Record<string, any>;
}

export interface ConnectorModuleCreateConnectorNameDialogSetupState {

}

export enum ConnectorModuleCreateConnectorNameDialogEmitEventNameEnum {
  Input = 'input',
  Close = 'close',
  Next = 'next',
}

export type ConnectorModuleCreateConnectorNameDialogInstance = ComponentInstance & ConnectorModuleCreateConnectorNameDialogSetupState
export type ConnectorModuleCreateConnectorNameDialogVM = ComponentRenderProxy<ConnectorModuleCreateConnectorNameDialogProps> & CommonComponentInstance & ConnectorModuleCreateConnectorNameDialogInstance

export default defineComponent({
  name: ConnectorModuleComponentNameEnum.ConnectorModuleCreateConnectorNameDialog,
  components: {
    [addComponentNamePrefix(FormCascader.name)]: FormCascader
  },
  emits: [
    ConnectorModuleCreateConnectorNameDialogEmitEventNameEnum.Input,
    ConnectorModuleCreateConnectorNameDialogEmitEventNameEnum.Close,
    ConnectorModuleCreateConnectorNameDialogEmitEventNameEnum.Next,
  ],
  props: {
    disabled: {
      type: Boolean as PropType<boolean>,
      default: false,
    },
    nextDisabled: {
      type: Boolean as PropType<boolean>,
      default: false,
    },
    fields: {
      type: Array as PropType<Field[]>,
      default: () => [],
    },
    title: {
      type: String as PropType<string>,
      default: '',
    },
    value: {
      type: Object as PropType<Record<string, any>>,
      default: () => ({}),
    },
    visible: {
      type: Boolean as PropType<boolean>,
      default: false,
    },
    checkCreateConnector: {
      type: Function,
      default: () => ({})
    },
    isShowSelectLanguage: {
      type: Boolean as PropType<boolean>,
      default: false,
    }
  },
  setup(props: ConnectorModuleCreateConnectorNameDialogProps, { emit }) {

    const { visible: insideVisible, showDialog, hideDialog } = useDialog()
    const { loading: fetchModuleListItemLoading, fetchModuleItemList, moduleListItem } = useConnectorCardSettingFetchModuleList()

    const currentCascaderItem = ref(null)

    const formBuildComponentRef = 'FormBuilderComponent'

    const onDialogCloseHandler = () => {
      // 关闭清除对应的缓存
      storageRm(StorageModuleEnum.Connector, ConnectorFetchAppModulesStorageKey)

      emit(ConnectorModuleCreateConnectorNameDialogEmitEventNameEnum.Close)
    }

    const onDialogNextHandler = () => {
      emit(ConnectorModuleCreateConnectorNameDialogEmitEventNameEnum.Next, currentCascaderItem.value)
    }

    watch(() => props.visible, (newValue) => {
      if (newValue) {
        showDialog()
      } else {
        hideDialog()
      }
    }, {
      immediate: true,
    })

    // 多语灰度
    const isMultiLanguage = computed(() => {
      const RootWindow = getRootWindow(window);
      return RootWindow.grayAuth?.multiLanguage ?? false;
    });
    
    return {
      insideVisible,
      formBuildComponentRef,
      currentCascaderItem,
      moduleListItem,
      fetchModuleItemList,

      isMultiLanguage,
      showDialog,
      hideDialog,

      onDialogCloseHandler,
      onDialogNextHandler,
    }
  },
  methods: {
    /**
     * @description 取消
    */
    cancel() {
      this.hideDialog()
      this.onDialogCloseHandler()
    },
    /**
    * @description 获取属性列表
    * @return {Record<string, any>} 属性列表
    */
    getAttributes(): Record<string, any> {
      return {
        class: ConnectorModuleComponentNameEnum.ConnectorModuleCreateConnectorNameDialog,
        props: {
          title: this.title,
          show: this.insideVisible,
          appendToBody: true
        },
        on: {
          'update:show': () => {
            this.hideDialog()
          },
          'closed': () => {
            this.onDialogCloseHandler()
          }
        }
      }
    },
    /**
     * @description 下一步
    */
    async next() {

      const formBuildComponent: Record<string, any> = this.$refs[this.formBuildComponentRef]

      if (isFalsy(formBuildComponent)) {
        Log.warn('[create-connector-name-dialog] FormBuilderComponent Does not exist')
        return
      }

      const validated = await formBuildComponent.validate()

      if (isFalsy(validated)) {
        Log.warn('[create-connector-name-dialog] FormBuilderComponent validate failed')
        return
      }

      this.onDialogNextHandler()
    },
    /**
     * @description: 更新事件
     * @param {FieldUpdateResult} param
     * @return {void}
    */
    update({ field, newValue }: FieldUpdateResult): void {

      if(field.formType === 'cascader') {
        this.currentCascaderItem = this.findTreeItemForArrayData(cloneDeep(newValue))
      }
      
      this.$emit(ConnectorModuleCreateConnectorNameDialogEmitEventNameEnum.Input, field, newValue)
    },
    /**
     * @description: 渲染表单作用域插槽
     * @return {VNode | null} 插槽或空
     */
    renderFormBuilderScopedSlot(h: CreateElement) {
      if(!this.isShowSelectLanguage && !this.isMultiLanguage) {
        return {
          [CreateConnectorDialogFieldNameEnum.RelationAppForm]: (
            (data: CreateConnectorDialogFormBuilderScopedSlotDataType) => this.renderFormBuilderScopedSlotRelationAppForm(h, data)
          )
        }
      }

      return {
        [CreateConnectorDialogFieldNameEnum.RelationAppForm]: (
          (data: CreateConnectorDialogFormBuilderScopedSlotDataType) => this.renderFormBuilderScopedSlotRelationAppForm(h, data)
        ),
        [CreateConnectorDialogFieldNameEnum.Name]: (
          (data: CreateConnectorDialogFormBuilderScopedSlotDataType) => this.renderFormBuilderScopedSlotName(h, data)
        ),
        [CreateConnectorDialogFieldNameEnum.Description]: (
          (data: CreateConnectorDialogFormBuilderScopedSlotDataType) => this.renderFormBuilderScopedSlotDescription(h, data)
        ),
      }
    },
    renderFormBuilderScopedSlotRelationAppForm(h: CreateElement, data: CreateConnectorDialogFormBuilderScopedSlotDataType) {

      const field = data?.field || {}
      const value = data?.value || []

      const setting = field?.setting || {}
      const dataSource = setting?.dataSource || []


      const handleCascaderItemClick = (e: MouseEvent, { node, data }: Record<string, any>) => {
        // 这里判断是否是倒数第二级的可选
        if(data?.canSelect) {
          // eslint-disable-next-line @typescript-eslint/ban-ts-comment
          // @ts-ignore
          const target = e.target.parentNode.previousElementSibling
          target.click()
          this.currentCascaderItem = data
          // const { path, value = ''} = node
          // this.update({ field, newValue: path, oldValue: null });
          const cascaderRef = (this.$refs['publinkFormCascader'] as unknown as any)?.$children?.[0];
          cascaderRef.suggestions = [];
          cascaderRef.$nextTick(()=> cascaderRef.dropDownVisible = false)
        }
        // 选择完清除对应的缓存
        storageRm(StorageModuleEnum.Connector, ConnectorFetchAppModulesStorageKey)
      }
      // eslint-disable-next-line @typescript-eslint/no-this-alias
      const that = this

      const attrs = {
        props: {
          propsV2: {
            value: 'value',
            label: 'label',
            checkStrictly: true,
            lazy: true,
            async lazyLoad (node: Record<string, any>, resolve: (arg0: any) => void) {
              const { level, data } = node;
              // 当在第二层级的时候去加载另一个接口获取对应的列表
              if(level === 2) {
                await that.fetchModuleItemList({ appId: data?.appId || '' })
                const addUniqueIdDataList = addConnectorModuleUniqueIdEveryLevel(that.moduleListItem)
                return resolve(connectorAppModuleToFormCascaderDataSource(addUniqueIdDataList, true))
              }
              resolve(node)
            }
          }
        },
        scopedSlots:{
          default: ({node, data}: Record<string, any>)=> {
            const appLevel = node.level === 1 || node.level === 2
            return (
              data
                ? <span
                  // class={ !data.canSelect && !appLevel ? 'el-cascader-panel-item__label-disabled' : 'el-cascader-panel-item__label'}
                  class='el-cascader-panel-item__label'
                  onClick={(e: MouseEvent)=> handleCascaderItemClick(e, {node, data})}>
                  { data.label }
                </span>
                : null
            )
          }
        }
      }

      return (
        <form-item label={field.displayName} validation={this.checkConnectorValidation}>
          <publink-form-cascader
            ref="publinkFormCascader"
            popperClass="connector-module-create-connector-name__cascader"
            placeholder={field.placeHolder}
            version="new"
            field={field}
            tree={dataSource}
            value={value}
            onUpdate={this.update}
            {...attrs}
          >
          </publink-form-cascader>
        </form-item>
      )
    },
    checkConnectorValidation(){
      return new Promise((resolve, reject) => {
        // @ts-ignore
        this.checkCreateConnector(this.currentCascaderItem).then((result)=>{
          resolve(null)
          // @ts-ignore
        }).catch(error=>{
          // console.log('error', error)
          resolve(error?.message || t('common.connector.tips.tip9'))
        })
      })
    },
    // 名称
    renderFormBuilderScopedSlotName(h: CreateElement, data: CreateConnectorDialogFormBuilderScopedSlotDataType) {
      const field = data?.field || {}
      const value = data?.value || ''
      
      return (
        <form-item label={field.displayName} class="form-item-language">
          <form-text field={field} value={value} onUpdate={(e: any) => {
              this.update(e);
              this.update({ field: { fieldName: CreateConnectorDialogFieldNameEnum.TitleLanguage }, newValue: { ...(field?.defaultValueLanguage || {}), [locales.locale]: e.newValue }, oldValue:''});
            }} />
          { this.renderFormBuilderScopedSlotLanguage(field, value, CreateConnectorDialogFieldNameEnum.TitleLanguage, 'text') }
        </form-item>
      )
    },
    // 说明
    renderFormBuilderScopedSlotDescription(h: CreateElement, data: CreateConnectorDialogFormBuilderScopedSlotDataType) {
      const field = data?.field || {}
      const value = data?.value || ''
      
      return (
        <form-item label={field.displayName} class="form-item-language">
          <form-textarea field={field} value={value} onUpdate={(e: any) => {
              this.update(e);
              this.update({ field: { fieldName: CreateConnectorDialogFieldNameEnum.DescLanguage }, newValue: { ...(field?.defaultValueLanguage || {}), [locales.locale]: e.newValue}, oldValue:''});
            }} />
          { this.renderFormBuilderScopedSlotLanguage(field, value, CreateConnectorDialogFieldNameEnum.DescLanguage, 'textarea') }
        </form-item>
      )
    },
    // 小地球
    renderFormBuilderScopedSlotLanguage(field: Field, value: string | string[], type: string, formType: string) {
      return (
        <base-select-language 
          field={field}
          defaultOption={{
            formType: formType,
          }}
          defaultFormType={formType}
          defaultValue={value}
          defaultValueLanguage={field.defaultValueLanguage || {}}
          onSave={(e: any) => this.languageSave(e, field, type)}
        >
        </base-select-language>
      )
    },
    languageSave(data: any, field: Field, fieldName: string){
      // 默认字体数据回填
      if(field.defaultValue !== data[locales.locale]){
        this.update({ field, newValue: data[locales.locale], oldValue: field.defaultValue });
      }
      this.update({
        field: { fieldName },
        newValue: data,
        oldValue: ''
      });
    },
    findTreeItemForArrayData( dataArr: string[]): any {
      const lastKey = dataArr.pop()
      // @ts-ignore
      const suggestionsList = this.$refs?.publinkFormCascader?.$children[0]?.suggestions || []
      if(!suggestionsList.length) return this.currentCascaderItem
      return suggestionsList.find((item: any)=> item.data?.value === lastKey)?.data || null
    }
  },
  render(h: CreateElement) {

    const attrs = this.getAttributes()

    return (
      <base-modal {...attrs}>

        {this.insideVisible && (
          <form-builder
            ref={this.formBuildComponentRef}
            fields={this.fields}
            value={this.value}
            onUpdate={this.update}
            scopedSlots={this.renderFormBuilderScopedSlot(h)}
          >
          </form-builder>
        )}

        <div class="dialog-footer" slot="footer">

          <el-button
            disabled={this.disabled}
            onClick={this.cancel}
          >
            {t('common.base.cancel')}
          </el-button>

          <el-button
            type="primary"
            disabled={this.disabled || this.nextDisabled}
            onClick={this.next}
          >
            {t('common.base.steps.next')}
          </el-button>

        </div>

      </base-modal>
    )
  }
})
